home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994…tember: Reference Library / Dev.CD Sep 94.toast / Periodicals / develop / develop Issue 19 / develop 19 code / Adding GX Printing to QD Apps / Simple Sample ƒ / menus & windows.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-15  |  19.3 KB  |  790 lines  |  [TEXT/KAHL]

  1. /*********************************************************************
  2.  
  3.     menus & windows.c
  4.     
  5.     This file contains the menu and window handling code for the
  6.     QuickDraw GX unaware sample, "Simple Sample."
  7.  
  8.     Additional info can be found in the related develop #19 article,
  9.     "Adding QuickDraw GX Printing to QuickDraw Applications."
  10.  
  11.     Dave Hersey, Apple Developer Technical Support.
  12.     
  13.     ——————— Edit Trail ———————
  14.     
  15.     constructed:                                    1/22/94  - dmh
  16.     cleaned up for 2nd draft of develop article:    3/10/94  - dmh
  17.     cleaned up for final:                            4/14/94  - dmh
  18.     
  19. *********************************************************************/
  20.  
  21. #include "Simple Sample.h"
  22.  
  23.  
  24. /************************************************************
  25.   MyCreateDocument - This routine is called to create a new
  26.   document.
  27.  
  28. *************************************************************/
  29.  
  30. OSErr MyCreateDocument(char *docTitle, MyDocumentPtr *createdDocument)
  31. {
  32.     OSErr            err;
  33.     WindowPtr        documentWindow;
  34.     long            newPage;
  35.  
  36.     *createdDocument = nil;
  37.  
  38. // Create a window for our document.
  39.  
  40.     documentWindow = (WindowPtr) NewCWindow(nil, &gWindowRect, (ConstStr255Param) docTitle, false, noGrowDocProc, (WindowPtr)-1L, true, 0L);
  41.     require_action(documentWindow, CouldNotCreateWindow, err = MemError(););
  42.  
  43. // Initialize our private data for the document.
  44.  
  45.     *createdDocument = (MyDocumentPtr) NewPtrClear(sizeof(MyDocumentRec));
  46.     require_action(*createdDocument, CouldNotCreateDocRec, err = MemError(););
  47.  
  48. //    Create a print handle.
  49.  
  50.     (*createdDocument)->documentPrintHdl = (THPrint) NewHandle(sizeof(TPrint));
  51.     err = MemError();
  52.  
  53.     if (!err)
  54.     {
  55.         PrOpen();
  56.         PrintDefault((*createdDocument)->documentPrintHdl);
  57.         PrClose();
  58.     }
  59.  
  60. /*
  61.     If there were no errors, add 1 page to the document, and
  62.     store a reference to our private data in the document's
  63.     window's refCon field.
  64. */
  65.     nrequire(err, CouldNotCreatePrintStuff);
  66.     
  67.     (*createdDocument)->numPages = 0;
  68.     (*createdDocument)->documentWindow = documentWindow;
  69.     (*createdDocument)->documentFSSpec.name[0] = 0;        // Indicates that document has never
  70.                                                         // been saved.
  71.     if (docTitle[0] > 31)
  72.         docTitle[0] = 31;
  73.  
  74.     BlockMove(&docTitle[0], &(*createdDocument)->documentTitle[0], (long) docTitle[0] +1);
  75.     newPage = 0;
  76.     err = MyInsertPage(*createdDocument, &newPage);
  77.     (*createdDocument)->curPage = newPage;
  78.  
  79. // Set the refCon to point to our document info structure.
  80.  
  81.     nrequire(err, CouldNotInsertPage);
  82.     SetWRefCon(documentWindow, (long) *createdDocument);
  83.     require(err, NoProblems);
  84.  
  85. CouldNotInsertPage:
  86.     DisposHandle((Handle) (*createdDocument)->documentPrintHdl);
  87.  
  88. CouldNotCreatePrintStuff:
  89.     DisposePtr((Ptr) *createdDocument);
  90.  
  91. CouldNotCreateDocRec:
  92.     DisposeWindow(documentWindow);
  93.  
  94. CouldNotCreateWindow:
  95. NoProblems:
  96.     return err;
  97. }
  98.  
  99.  
  100. /************************************************************
  101.   MyDisposeDocument - This routine is called when we need to
  102.   dispose of a window.
  103.  
  104. *************************************************************/
  105.  
  106. void MyDisposeDocument(MyDocumentPtr whichDocument)
  107. {
  108.     long        numPages, pg;
  109.     WindowPtr    docWindow;
  110.     
  111. // Dispose of our private data for each page of this document.
  112.  
  113.     numPages = whichDocument->numPages;
  114.  
  115.     for (pg = numPages; pg >= 1; pg--)
  116.         MyDisposePage(whichDocument, pg);
  117.  
  118. //    Dispose of our document's print record and private data.
  119.  
  120.     if (whichDocument->documentPrintHdl != nil)
  121.         DisposHandle((Handle) whichDocument->documentPrintHdl);
  122.     
  123.        DisposeWindow(whichDocument->documentWindow);
  124.     DisposePtr((Ptr) whichDocument);
  125. }
  126.  
  127.  
  128. /************************************************************
  129.   MyInsertPage - This routine is called when we need to add
  130.   a page to a document.  The page is added AFTER the page
  131.   number passed (1-based).  If whichPg is greater than the
  132.   last page of the document, the new page is added to the
  133.   end of the document.  If whichPg is less than 1, the page
  134.   is added to the beginning of the doc.  The page number of
  135.   the new page is returned in whichPg.
  136.  
  137. *************************************************************/
  138.  
  139. OSErr MyInsertPage(MyDocumentPtr whichDocument, long *whichPage)
  140. {
  141.     OSErr        err = noErr;
  142.     long        numPages, aPage;
  143.     long        newSize;
  144.  
  145. // Pin the number of the page to add to the range (1, numPages +1).
  146.  
  147.     numPages = whichDocument->numPages;
  148.     *whichPage = (*whichPage < 1)? 1: (*whichPage < numPages)? *whichPage +1: numPages +1;
  149.  
  150. /*
  151.     Do whatever you need to do to add page data here.
  152.     .
  153.     .
  154.     .
  155.     
  156. */
  157.  
  158.     numPages = ++whichDocument->numPages;
  159.     return err;
  160. }
  161.  
  162.  
  163. /************************************************************
  164.   MyDisposePage - This routine is called when we need to
  165.   dispose of a page in a document.
  166.  
  167. *************************************************************/
  168.  
  169. void MyDisposePage(MyDocumentPtr whichDocument, long whichPage)
  170. {
  171.     long        numPages, pageNum;
  172.     long        newSize;
  173.  
  174. // Idiot control.
  175.  
  176.     if (whichPage > whichDocument->numPages) return;    // ?!  There aren't that many pages!!
  177.     if (whichPage < 1) return;                            // ?!  Page numbers start at 1!!
  178.  
  179. /*
  180.     Do whatever you need to do to remove page data here.
  181.     .
  182.     .
  183.     .
  184.     
  185. */
  186.  
  187. // We now have one less page in our document.
  188.  
  189.     numPages = --whichDocument->numPages;
  190. }
  191.  
  192.  
  193. /************************************************************
  194.   MyUpdateWindow - This routine simply updates the passed
  195.   window.
  196.  
  197. *************************************************************/
  198.  
  199. void MyUpdateWindow(WindowPtr whichWindow)
  200. {
  201.     GrafPtr        oldPort;
  202.  
  203. // Update the indicated window.
  204.  
  205.     if (((WindowPeek) whichWindow)->windowKind == userKind)
  206.     {
  207.         GetPort(&oldPort);
  208.         SetPort(whichWindow);
  209.         BeginUpdate(whichWindow);
  210.         MyDrawContents(whichWindow);
  211.         EndUpdate(whichWindow);
  212.         SetPort(oldPort);
  213.     }
  214. }
  215.  
  216.  
  217. /************************************************************
  218.   MyDrawContents - This routine draws the contents of a
  219.   window.  Note that this same code is used to draw during
  220.   printing.  All we do in this code is make a bunch of
  221.   QuickDraw calls to draw our document's pages.
  222.  
  223. *************************************************************/
  224.  
  225. void MyDrawContents(WindowPtr whichWindow)
  226. {
  227.     MyDocumentPtr    windowDoc;
  228.     PicHandle        drawPict;
  229.     Rect            drawRect, drawRect2;
  230.     short            fNum, i, lineInc, hCenter, picWidth, picHeight;
  231.     short            oldResFile;
  232.     FontInfo        fInfo;
  233.     Handle            iconHdl;
  234.     BitMap            iconBitMap;
  235.     Str255            pStr;
  236.     Point            where;
  237.     GrafPtr            curPort;
  238.  
  239. //    Preserve the current resource file in case we're printing.
  240.  
  241.     oldResFile = CurResFile();
  242.     windowDoc = MyGetDocPtr(whichWindow);
  243.  
  244. // Draw a red QuickDraw rectangle.
  245.  
  246.     ForeColor(redColor);
  247.     SetRect(&drawRect, 20, 20, 150, 150);
  248.     FrameRect(&drawRect);
  249.  
  250. // Draw a blue QuickDraw oval.
  251.  
  252.     ForeColor(blueColor);
  253.     OffsetRect(&drawRect, 40, 40);
  254.     FrameOval(&drawRect);
  255.  
  256. // Draw a black QuickDraw line with a 4x4 pen.
  257.  
  258.     ForeColor(blackColor);
  259.     PenSize(4, 4);
  260.     MoveTo(drawRect.left, drawRect.top);
  261.     LineTo(drawRect.right, drawRect.bottom);
  262.     PenSize(1, 1);
  263.  
  264. // Draw some QuickDraw text with various faces.
  265.  
  266.     GetFNum("\pNew York", &fNum);
  267.     TextFont(fNum);
  268.     TextSize(10);
  269.     GetFontInfo(&fInfo);
  270.     lineInc = fInfo.ascent + fInfo.leading + fInfo.descent;
  271.     TextFace(bold);
  272.     MoveTo(220, 40);
  273.     DrawString("\pFor Sale: ");
  274.     TextFace(0);
  275.     DrawString("\pEnglish sheepdog.  ");
  276.     TextFace(underline);
  277.     DrawString("\pCompletely");
  278.     TextFace(0);
  279.     MoveTo(220, 40 + lineInc);
  280.     DrawString("\phouse-broken, eats a lot, ");
  281.     TextFace(italic);
  282.     DrawString("\ploves cats and");
  283.     MoveTo(220, 40 + 2* lineInc);
  284.     DrawString("\psmall children.");
  285.     TextFace(0);
  286.     DrawString("\p  Free to a good home.");
  287.     MoveTo(220, 40 + 3* lineInc);
  288.  
  289. // Draw two concentric QuickDraw rectangles around the text we just drew.
  290.  
  291.     GetPen(&where);
  292.     drawRect.left = 216;
  293.     drawRect.top = 30;
  294.     drawRect.right = 450;
  295.     drawRect.bottom = where.v - lineInc/2;
  296.     FrameRect(&drawRect);
  297.     InsetRect(&drawRect, -2, -2);
  298.     FrameRect(&drawRect);
  299.  
  300. /*
  301.     Calculate the center of our window, and then draw a
  302.     QuickDraw picture at that location.
  303. */
  304.  
  305.     hCenter = (whichWindow->portRect.right + whichWindow->portRect.left) >>1;
  306.  
  307.     UseResFile(gAppResRefNum);
  308.     drawPict = GetPicture(r_documentPict);
  309.     UseResFile(oldResFile);
  310.  
  311.     if (drawPict != nil) 
  312.     {
  313.         picWidth = (*drawPict)->picFrame.right - (*drawPict)->picFrame.left;
  314.         picHeight = (*drawPict)->picFrame.bottom - (*drawPict)->picFrame.top;
  315.         
  316.         drawRect.top = 240;
  317.         drawRect.left = hCenter -(picWidth >>1);
  318.         drawRect.bottom = drawRect.top + picHeight;
  319.         drawRect.right = drawRect.left + picWidth;
  320.          
  321.         DrawPicture(drawPict, &drawRect);
  322.         ReleaseResource((Handle) drawPict);
  323.     }
  324.  
  325. /*
  326.     Load a QuickDraw icon, and CopyBits a bunch of them across
  327.     the page, in various colors.
  328. */
  329.  
  330.     UseResFile(gAppResRefNum);
  331.     iconHdl = (Handle) GetIcon(r_documentBitmap);
  332.     UseResFile(oldResFile);
  333.  
  334.     if (iconHdl != nil)
  335.     {
  336.         MoveHHi((Handle) iconHdl);
  337.         HLock((Handle) iconHdl);
  338.         iconBitMap.rowBytes = 4;
  339.         SetRect(&iconBitMap.bounds, 0, 0, 31, 31);
  340.         iconBitMap.baseAddr = *iconHdl;
  341.         
  342.         drawRect.top = drawRect.bottom +20;
  343.         drawRect.left = 10;
  344.         drawRect.bottom = drawRect.top +31;
  345.         drawRect.right = drawRect.left +31;
  346.         
  347.         for (i = 0; i < 12; i++)
  348.         {
  349.             switch (i % 6)
  350.             {
  351.                 case 0:
  352.                     ForeColor(blackColor);
  353.                     break;
  354.                 case 1:
  355.                     ForeColor(blueColor);
  356.                     break;
  357.                 case 2:
  358.                     ForeColor(greenColor);
  359.                     break;
  360.                 case 3:
  361.                     ForeColor(redColor);
  362.                     break;
  363.                 case 4:
  364.                     ForeColor(cyanColor);
  365.                     break;
  366.                 case 5:
  367.                     ForeColor(magentaColor);
  368.                     break;
  369.             }
  370.             
  371.             GetPort(&curPort);
  372.             CopyBits(&iconBitMap, &curPort->portBits, &iconBitMap.bounds, &drawRect, srcCopy, nil);
  373.     
  374.             drawRect.left  += 40;
  375.             drawRect.right += 40;
  376.         }
  377.         
  378.         ReleaseResource(iconHdl);
  379.     }
  380.  
  381. // Draw some more QuickDraw text.  This time, blue and 24 point.
  382.  
  383.     GetFNum("\pTimes", &fNum);
  384.     TextFont(fNum);
  385.     TextSize(24);
  386.     ForeColor(blueColor);
  387.     pStr[0] = sprintf((char *) &pStr[1], "These are some typical QuickDraw objects");
  388.     MoveTo(hCenter -(StringWidth(pStr) >>1), drawRect.bottom +20);
  389.     DrawString(pStr);
  390.  
  391. // Draw some QuickDraw PicComments.
  392.  
  393.     MyDrawPicComments();
  394.  
  395. /*
  396.     Draw some more black QuickDraw text in a different font
  397.     and size, indicating the page number.
  398. */
  399.     GetFNum("\pGeneva", &fNum);
  400.     TextFont(fNum);
  401.     TextSize(12);
  402.     
  403.     ForeColor(blackColor);
  404.     pStr[0] = sprintf((char *) &pStr[1], "This is page %ld of %ld.",
  405.                       windowDoc->curPage, windowDoc->numPages);
  406.  
  407.     MoveTo(hCenter -(StringWidth(pStr) >>1), drawRect.bottom +80);
  408.     DrawString(pStr);
  409. }
  410.  
  411.  
  412. /************************************************************
  413.   MyDrawPicComments - This routine just draws some example
  414.   PicComments which will make a PostScript device display
  415.   "This was drawn on a PostScript device." and other devices
  416.   display "This was drawn on a non-PostScript device."  We
  417.   use PostScriptBegin PostScriptEnd and PostScriptHandle.
  418.  
  419. *************************************************************/
  420.  
  421. void MyDrawPicComments()
  422. {
  423.     short        fNum;
  424.  
  425. /*
  426.     Draw some QuickDraw to set the PS clip, not necessary in
  427.     this case, but if we hadn't made any QuickDraw calls yet,
  428.     the PostScript clip wouldn't get set, and *everything*
  429.     would be clipped.  This code, which doesn't actually draw
  430.     anything, is here as a reminder.
  431. */
  432.  
  433.     PenSize(0, 0);
  434.     MoveTo(0, 0); 
  435.     Line(0, 0);
  436.     PenSize(1, 1);
  437.  
  438. /*
  439.     PostScriptBegin tells a PostScript driver to ignore Quickdraw
  440.     calls until it receives a PostScriptEnd picture comment.
  441.     This line is ignored by non-PostScript printer drivers.
  442. */
  443.  
  444.     PicComment(PostScriptBegin, 0, nil);
  445.  
  446. /*
  447.     QuickDraw representation. These calls will only be executed by
  448.     QuickDraw printers.  Set the font to Times Italic 14 pt and then
  449.     move and draw.
  450. */
  451.  
  452.     GetFNum("\pTimes", &fNum);
  453.     TextFont(fNum);
  454.     TextSize(14);
  455.     TextFace(italic);
  456.     MoveTo(127, 227);
  457.     DrawString("\pThis was drawn on a non-PostScript device.");
  458.     TextFace(0);
  459.  
  460. /*
  461.     PostScript representation. These calls will only be executed by
  462.     PostScript printers.  We draw the same as above, sans the "non-"
  463.     and shifted left a tad.
  464. */
  465.  
  466.     MySendPostScript("\p0 760 translate 1 -1 scale");
  467.     MySendPostScript("\p/Times-Italic findfont 14 scalefont setfont");
  468.     MySendPostScript("\p135 533 moveto (This was drawn on a PostScript device.) show");
  469.  
  470. /*
  471.     PostScriptEnd tells a PostScript driver to start executing
  472.     QuickDraw calls normally again.
  473. */
  474.  
  475.     PicComment(PostScriptEnd, 0, nil);
  476. }
  477.  
  478.  
  479. /************************************************************
  480.   MySendPostScript - This routine just packages the passed
  481.   Pascal string into a handle and sends the PostScriptHandle
  482.   PicComment.
  483.  
  484. *************************************************************/
  485.  
  486. void MySendPostScript(Str255 thePostScript)
  487. {
  488.     OSErr    err;
  489.     Handle    thePSHdl;
  490.     Ptr        thePSPtr;
  491.     long    textLen;
  492.  
  493. /*
  494.     Create a handle for the passed string plus a carriage
  495.     return.  Move the string's data into the handle, stuff a
  496.     carriage return on the end, call PicComment, and finally
  497.     dispose of the handle.
  498. */
  499.     textLen = thePostScript[0];
  500.     thePSHdl = TempNewHandle(textLen +1, &err);
  501.  
  502.     if (!err)
  503.     {
  504.         thePSPtr = *thePSHdl;
  505.         BlockMove(&thePostScript[1], thePSPtr, textLen);
  506.         *(thePSPtr +textLen) = (char) 13; //carriage return.
  507.         ++textLen;
  508.  
  509.         PicComment(PostScriptHandle, textLen, thePSHdl);
  510.         DisposHandle(thePSHdl);
  511.     }
  512. }
  513.  
  514.  
  515. /************************************************************
  516.   MyAdjustMenus - This routine enables and disables our
  517.   menus and menu items.
  518.  
  519. *************************************************************/
  520.  
  521. void MyAdjustMenus()
  522. {
  523.     WindowPtr        activeWindow;
  524.     MenuHandle        appleMenu, fileMenu, editMenu, documentMenu;
  525.     MyDocumentPtr    activeDocument;
  526.     Boolean            docOpen, onFirstPage, onLastPage, maxPages, neverSaved;
  527.  
  528.     appleMenu = GetMHandle(mApple);
  529.     editMenu = GetMHandle(mEdit);
  530.     fileMenu = GetMHandle(mFile);
  531.     documentMenu = GetMHandle(mDocument);
  532.  
  533.     EnableItem(appleMenu, iAbout);
  534.     EnableItem(fileMenu,  iQuit);
  535.     EnableItem(fileMenu,  iNew);
  536.     EnableItem(fileMenu,  iOpen);
  537.  
  538. /*
  539.     If we have a document open, we enable certain menu items.
  540.     Otherwise, we don't.
  541. */
  542.  
  543.     activeWindow = FrontWindow();
  544.  
  545.     if (activeWindow)
  546.     {
  547.         if (((WindowPeek) activeWindow)->windowKind != userKind)
  548.             activeWindow = nil;
  549.     }
  550.  
  551.     docOpen = (activeWindow != nil);
  552.  
  553.     if (!docOpen)                                        // No document open.
  554.     {
  555.         DisableItem(fileMenu, iPrint);
  556.         DisableItem(fileMenu, iClose);
  557.         DisableItem(fileMenu, iSave);
  558.         DisableItem(fileMenu, iSaveAs);
  559.         DisableItem(fileMenu, iPageSetup);
  560.         DisableItem(documentMenu, iInsertPage);
  561.         DisableItem(documentMenu, iDeletePage);
  562.         DisableItem(documentMenu, iAheadPage);
  563.         DisableItem(documentMenu, iBackPage);
  564.     }
  565.     else                                                // A document is open.
  566.     {
  567.         EnableItem(fileMenu, iPrint);
  568.         EnableItem(fileMenu, iClose);
  569.         EnableItem(fileMenu, iPageSetup);
  570.         EnableItem(fileMenu, iSaveAs);
  571.  
  572. /*
  573.     Enable/disable items based on the number of pages in our document,
  574.     whether we're on the first or last page, and whether or not it's
  575.     been saved yet.
  576. */
  577.         activeDocument = MyGetDocPtr(activeWindow);
  578.  
  579.         if (activeDocument->numPages > 1)                // Got at least one page?
  580.             EnableItem(documentMenu, iDeletePage);
  581.         else
  582.             DisableItem(documentMenu, iDeletePage);
  583.  
  584.         onFirstPage = (activeDocument->curPage == 1);
  585.         onLastPage = (activeDocument->curPage == activeDocument->numPages);
  586.         maxPages = (activeDocument->numPages == kMaxPages);
  587.         neverSaved = (activeDocument->documentFSSpec.name[0] == 0);
  588.  
  589.         if (neverSaved)                                    // Never saved this document?
  590.             DisableItem(fileMenu, iSave);
  591.         else
  592.             EnableItem(fileMenu, iSave);
  593.  
  594.         if (!maxPages)                                    // Can still add more pages?
  595.             EnableItem(documentMenu, iInsertPage);
  596.         else
  597.             DisableItem(documentMenu, iInsertPage);
  598.  
  599.         if (!onLastPage)                                // Not on last page?
  600.             EnableItem(documentMenu, iAheadPage);
  601.         else
  602.             DisableItem(documentMenu, iAheadPage);
  603.  
  604.         if (!onFirstPage)                                // Not on first page?
  605.             EnableItem(documentMenu, iBackPage);
  606.         else
  607.             DisableItem(documentMenu, iBackPage);
  608.     }
  609. }
  610.  
  611.  
  612. /************************************************************
  613.   MyDoMenuCommand - This routine handles the dispatching of
  614.   our menu requests.
  615.  
  616. *************************************************************/
  617.  
  618. void MyDoMenuCommand(long menuResult)
  619. {
  620.     short                menuID, menuItem;
  621.     long                curPage, numPages, newPage;
  622.     Str255                daName;
  623.     OSErr                err;
  624.     WindowPtr            activeWindow;
  625.     MyDocumentPtr        activeDocument, aDocument;
  626.  
  627.     menuID = menuResult >>16;
  628.     menuItem = menuResult & 0x0000FFFF;
  629.     activeWindow = FrontWindow();
  630.     activeDocument = MyGetDocPtr(activeWindow);
  631.  
  632.     switch (menuID)
  633.     {
  634.         case mApple:
  635.             switch (menuItem)
  636.             {
  637.                 case iAbout:                    // About.
  638.  
  639.                     Alert(r_About, nil);
  640.                     break;
  641.                 
  642.                 default:                        // DAs, etc.
  643.  
  644.                     GetItem(GetMHandle(mApple), menuItem, daName);
  645.                     OpenDeskAcc(daName);
  646.                     break;
  647.             }
  648.             break;
  649.             
  650.             case mFile:
  651.                 switch (menuItem)
  652.                 {                        
  653.                     case iNew:                    // New or Open.
  654.                     case iOpen:
  655.  
  656.                         err = MyCreateDocument(kDefaultTitle, &aDocument);
  657.  
  658.                         if ((err == noErr) && (menuItem == iOpen))
  659.                         {
  660.                             err = MyLoadDocument(aDocument);
  661.  
  662.                             if (err != noErr)
  663.                                 MyDisposeDocument(aDocument);
  664.                         }
  665.                         
  666.                         if (err == noErr)
  667.                         {
  668.                             ShowWindow(aDocument->documentWindow);
  669.                             SelectWindow(aDocument->documentWindow);
  670.                             MyAdjustMenus();
  671.                         }
  672.                         break;
  673.                                                 
  674.                     case iClose:                // Close.
  675.  
  676.                         MyDisposeDocument(activeDocument);
  677.                         break;
  678.                                                 
  679.                     case iSave:                    // Save or Save As.
  680.                     case iSaveAs:
  681.  
  682.                         err = MySaveDocument(activeDocument, (menuItem == iSaveAs));
  683.                         break;
  684.         
  685.                     case iPageSetup:            // Page Setup.
  686.  
  687.                         if (MyDoPageSetup(activeDocument))
  688.                             MyRepaginateDoc(activeDocument);
  689.                         break;
  690.  
  691.                     case iPrint:                // Print.
  692.  
  693.                         err = MyPrintDocument(activeDocument);
  694.                         break;
  695.  
  696.                     case iQuit:                    // Quitting.
  697.  
  698.                         gQuitting = true;
  699.                         break;
  700.                 }
  701.                 break;
  702.                 
  703.             case mEdit:  // If this were a real app, blah, blah, blah.
  704.                 break;
  705.                 
  706.             case mDocument:
  707.                 switch (menuItem)
  708.                 {                        
  709.                     case iInsertPage:            // Insert a page.
  710.                             
  711.                             newPage = activeDocument->curPage;
  712.                             MyInsertPage(activeDocument, &newPage);
  713.                             activeDocument->curPage = newPage;
  714.                             SetPort(activeWindow);
  715.                             EraseRect(&activeWindow->portRect);
  716.                             InvalRect(&activeWindow->portRect);
  717.                         break;
  718.                                                 
  719.                     case iDeletePage:            // Delete current page.
  720.                             
  721.                             curPage = activeDocument->curPage;
  722.                             numPages = activeDocument->numPages;
  723.  
  724.                             if (numPages > 1)
  725.                             {
  726.                                 MyDisposePage(activeDocument, curPage);
  727.  
  728.                                 if (curPage == numPages)
  729.                                     curPage = --activeDocument->curPage;
  730.                                 
  731.                                 SetPort(activeWindow);
  732.                                 EraseRect(&activeWindow->portRect);
  733.                                 InvalRect(&activeWindow->portRect);
  734.                             }
  735.                         break;
  736.                                                 
  737.                     case iAheadPage:            // Display ahead one page.
  738.                             
  739.                             curPage = activeDocument->curPage;
  740.                             numPages = activeDocument->numPages;
  741.  
  742.                             if (curPage < numPages)
  743.                             {
  744.                                 ++activeDocument->curPage;
  745.                                 
  746.                                 SetPort(activeWindow);
  747.                                 EraseRect(&activeWindow->portRect);
  748.                                 InvalRect(&activeWindow->portRect);
  749.                             }
  750.                         break;
  751.                                                 
  752.                     case iBackPage:                // Display back one page.
  753.                             
  754.                             curPage = activeDocument->curPage;
  755.  
  756.                             if (curPage > 1)
  757.                             {
  758.                                 --activeDocument->curPage;
  759.                                 
  760.                                 SetPort(activeWindow);
  761.                                 EraseRect(&activeWindow->portRect);
  762.                                 InvalRect(&activeWindow->portRect);
  763.                             }
  764.                         break;
  765.                 }
  766.                 break;
  767.     }
  768.  
  769.     HiliteMenu(0);
  770. }
  771.  
  772.  
  773. /************************************************************
  774.   MyGetDocPtr - This routine returns a pointer to the
  775.   private document structure our application attaches to
  776.   its windows.
  777.  
  778. *************************************************************/
  779.  
  780. MyDocumentPtr MyGetDocPtr(WindowPtr whichWindow)
  781. {
  782.     MyDocumentPtr    windowsDocument = nil;
  783.  
  784.     if (whichWindow != nil)
  785.         windowsDocument = (MyDocumentPtr) GetWRefCon(whichWindow);
  786.  
  787.     return windowsDocument;
  788. }
  789.  
  790.